package com.pingan.pastry.rpc.support;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class HttpInvoker implements InvocationHandler {

    private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());

    private String host;

    private int connectionTimeout;

    private int socketTimeout;

    private Map<Method,MethodHandler> methodHandlerCache = new ConcurrentHashMap();

    public HttpInvoker() {

    }

    public HttpInvoker(String host) {
        this.host = host;
    }

    public HttpInvoker(String host, int connectionTimeout, int socketTimeout) {
        this.host = host;
        this.connectionTimeout = connectionTimeout;
        this.socketTimeout = socketTimeout;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, args);
        }

        LOGGER.info("method:" + method.getName());
        long start = System.currentTimeMillis();
        MethodHandler methodHandler = cacheMethodHandler(method);
        Object result = methodHandler.handle(args, connectionTimeout, socketTimeout);
        long end = System.currentTimeMillis();
        LOGGER.info("远程调用耗时：" + (end - start));
        return result;
    }

    private MethodHandler cacheMethodHandler(Method method) {
        MethodHandler methodHandler = methodHandlerCache.get(method);
        if (methodHandler == null) {
            methodHandler = new MethodHandler(method, host);
            methodHandlerCache.put(method, methodHandler);
        }
        return methodHandler;
    }


    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getConnectionTimeout() {
        return connectionTimeout;
    }

    public void setConnectionTimeout(int connectionTimeout) {
        this.connectionTimeout = connectionTimeout;
    }

    public int getSocketTimeout() {
        return socketTimeout;
    }

    public void setSocketTimeout(int socketTimeout) {
        this.socketTimeout = socketTimeout;
    }

}
